#include "stdafx.h"
#include "DisasmExecMgr.h"

DisasmExecMgr::DisasmExecMgr(CONTEXT ct, InstructionManager* pInstructionMgr, IByteStreamReader* pDebugeeProcessReader):
m_ct(ct),
m_pInstructionMgr(pInstructionMgr),
m_debugProcessReader(pDebugeeProcessReader),
m_execRule(NULL),
m_segFS(0),
m_iCallLevel(1)
{
    InitCommands();
}

DisasmExecMgr::~DisasmExecMgr()
{
    m_memMap.clear();
    m_commands.clear();
    m_instructionStrArray.clear();

    if(m_pInstructionMgr != NULL)
    {
        delete m_pInstructionMgr;
        m_pInstructionMgr = NULL;
    }
    if(m_debugProcessReader != NULL)
    {
        delete m_debugProcessReader;
        m_debugProcessReader = NULL;
    }
    if(m_execRule != NULL)
    {
        delete m_execRule;
        m_execRule = NULL;
    }
}

void  DisasmExecMgr::AppendParameter(DWORD param)
{
    CString args;
    TCHAR paramStr[20];
    _ultow_s(param, paramStr, 20, 16);
    args = StrPush + StrSpace + paramStr;
    Execute(args);
}

bool DisasmExecMgr::StartExecute()
{
    if(m_pInstructionMgr == NULL)
        return false;
    void* WorkingEIP = NULL;
    CString instructionStr;
    while(true)
    {
        DWORD dSrcValue = (DWORD)(m_pInstructionMgr->GetByteReader()->GetCurrentBaseAddr());
        CString debugStr;
        debugStr.Format(_T("%#x "), dSrcValue);
        OutputDebugString(debugStr);
        if(!m_pInstructionMgr->GetOneInstruction(instructionStr))
            return false;
        m_instructionStrArray.push_back(instructionStr);
        if(!Execute(instructionStr))
            return false;
        OutputDebugString(_T("End Execute ") + instructionStr + StrEnter + StrEnter);
        if (m_pInstructionMgr->GetByteReader()->GetCurrentBaseAddr() == NULL)
            break;
    }
    return true;
}

bool DisasmExecMgr::Execute(CString disasmStr)
{
    if(m_execRule != NULL)
        m_execRule->PreExecute(disasmStr);
    //for(int i = 0; i < m_iCallLevel; i++)
    //  OutputDebugString(StrSpace);
    CString debugStr;
    debugStr.Format(_T("%d "), m_iCallLevel);
    debugStr = _T("  Current CallLevel: ") + debugStr;
    OutputDebugString(disasmStr + debugStr + StrEnter); 
    CString opCodeStr;
    if(!GetOperand(disasmStr, opCodeStr))
        return false;
    PFCOMMAND func;
    bool result = false;
    if(m_commands.find(opCodeStr) != m_commands.end())
    {
        func = m_commands[opCodeStr];
        result = (this->*func)(disasmStr);
    }
    else
        return false;
    if(m_execRule != NULL)
        m_execRule->PostExecute(disasmStr);
    return result;
}

void DisasmExecMgr::InitCommands()
{    
    m_commands[StrAdd] = &DisasmExecMgr::DoADD;
    m_commands[StrAnd] = &DisasmExecMgr::DoAND;
    m_commands[StrCall] = &DisasmExecMgr::DoCALL;
    m_commands[StrCmp] = &DisasmExecMgr::DoCMP;
    m_commands[StrInc] = &DisasmExecMgr::DoINC;
    m_commands[StrDec] = &DisasmExecMgr::DoDEC;
    m_commands[StrJE] = &DisasmExecMgr::DoJE;
    m_commands[StrJNE] = &DisasmExecMgr::DoJNE;
    m_commands[StrJNB] = &DisasmExecMgr::DoJAE;
    m_commands[StrJBE] = &DisasmExecMgr::DoJBE;
    m_commands[StrJA] = &DisasmExecMgr::DoJA;
    m_commands[StrJMP] = &DisasmExecMgr::DoJMP;
    m_commands[StrLea] = &DisasmExecMgr::DoLEA;
    m_commands[StrMov] = &DisasmExecMgr::DoMOV;
    m_commands[StrMovZX] = &DisasmExecMgr::DoMOVZX;
    m_commands[StrOR] = &DisasmExecMgr::DoOR;
    m_commands[StrPush] = &DisasmExecMgr::DoPUSH;
    m_commands[StrPop] = &DisasmExecMgr::DoPOP;
    m_commands[StrRet] = &DisasmExecMgr::DoRET;
    m_commands[StrSub] = &DisasmExecMgr::DoSUB;
    m_commands[StrSbb] = &DisasmExecMgr::DoSBB;
    m_commands[StrTest] = &DisasmExecMgr::DoTEST;
    m_commands[StrXor] = &DisasmExecMgr::DoXOR;
    m_commands[StrSAL] = &DisasmExecMgr::DoSAL;
    m_commands[StrSHR] = &DisasmExecMgr::DoSHR;
    m_commands[StrSetE] = &DisasmExecMgr::DoSETE; 
    m_commands[StrSetNE] = &DisasmExecMgr::DoSETNE;   
    m_commands[StrNeg] = &DisasmExecMgr::DoNEG;   
    m_commands[StrSTC] = &DisasmExecMgr::DoSTC;  
    m_commands[StrJB] = &DisasmExecMgr::DoJB;   
    m_commands[StrREP] = &DisasmExecMgr::DoREP;   
    m_commands[StrSTOS] = &DisasmExecMgr::DoSTOS;   
    m_commands[StrIMUL] = &DisasmExecMgr::DoIMUL;   
    m_commands[StrCMPXCHG] = &DisasmExecMgr::DoCMPXCHG;   
    m_commands[StrInterrupt] = &DisasmExecMgr::DoInterrupt;   
}

bool DisasmExecMgr::GetDescOperand(CString opCodeStr, CString & descOperand)
{
    int iSpacePos = opCodeStr.Find(StrSpace);
    if(iSpacePos == -1)
        return false;
    opCodeStr = opCodeStr.Right(opCodeStr.GetLength() - iSpacePos - 1);
    int iCommaPos = opCodeStr.Find(StrComma);
    if(iCommaPos == -1)
        descOperand = opCodeStr;
    else
        descOperand = opCodeStr.Left(iCommaPos);
    return true;
}

bool DisasmExecMgr::GetSrcOperand(CString opCodeStr, CString & srcOperand)
{
    int iSpacePos = opCodeStr.Find(_T(" "));
    if(iSpacePos == -1)
        return false;
    opCodeStr = opCodeStr.Right(opCodeStr.GetLength() - iSpacePos - 1);
    int iCommaPos = opCodeStr.Find(StrComma);
    if(iCommaPos == -1)
        return false;
    srcOperand = opCodeStr.Right(opCodeStr.GetLength() - iCommaPos - 1);
    return true;
}

bool DisasmExecMgr::GetSrcOperand2(CString opCodeStr, CString & srcOperand1, CString & srcOperand2)
{
  int iCommaPos = opCodeStr.Find(StrComma);
  if(iCommaPos == -1)
    return false;
  srcOperand1 = opCodeStr.Left(iCommaPos);
  srcOperand2 = opCodeStr.Right(opCodeStr.GetLength() - iCommaPos - 1);
  return true;
}

bool DisasmExecMgr::GetOperand(CString opCodeStr, CString & operand)
{
    int iSpacePos = opCodeStr.Find(StrSpace);
    if(iSpacePos < 1)
    {
        if(FindInstructionDNA(opCodeStr, StrRet))
        {
            operand = opCodeStr;         
            return true;
        }
        return false;
    }
    operand = opCodeStr.Left(iSpacePos);
    return true;
}

void* DisasmExecMgr::GetRetVal()
{
    void* ret = (void*)(m_ct.Eax);
    return ret;
}
void DisasmExecMgr::SetExecRule(IExecDisasmRule* execRule)
{
    m_execRule = execRule;
}

bool DisasmExecMgr::DoMOV(CString args)
{    
    CString descOperand;
    if(!GetDescOperand(args, descOperand))
        return false;
    CString srcOperand;
    if(!GetSrcOperand(args, srcOperand))
        return false;
    DWORD dSrcValue = GetSrcDWFromStr(srcOperand);
    dSrcValue = GetValueFromAddress(srcOperand, dSrcValue);
    // byte operator
    int bByteOp = 0;
    if(FindInstructionDNA(descOperand, StrBYTEPTR) )
    {
        descOperand.Replace(StrBYTEPTR, StrEmpty);
        bByteOp = 1;
    }
    else if (FindInstructionDNA(descOperand, StrDWORDPTR) )
    {
        descOperand.Replace(StrDWORDPTR, StrEmpty);
        bByteOp = 4;
    }
    else if (FindInstructionDNA(descOperand, StrWORDPTR) )
    {
        descOperand.Replace(StrWORDPTR, StrEmpty);
        bByteOp = 2;
    }
    else
    {
        bByteOp =  0;
    }
    // Mem add into memery map
    if(IsMemAddrFormat(descOperand))
    {
        descOperand.Replace(StrOpenBracket, StrEmpty);
        descOperand.Replace(StrCloseBracket, StrEmpty);   
        DWORD dwValue = 0;
        if(FindInstructionDNA(descOperand, StrFS))
        {
            CString strFSVA = descOperand;
            strFSVA.Replace(StrFS, StrEmpty);
            dwValue = GetFS() + PraseStr(strFSVA);
        }
        else
            dwValue = PraseStr(descOperand);
        // Need update here if dwValue is not aligned
        SetValueToAddress(dwValue, dSrcValue, bByteOp);
       
        TCHAR destMemValueStr[20];
        _ultow_s(dwValue, destMemValueStr, 20, 16);

        CString srcValueStr;
        srcValueStr.Format(_T("%#x "), dSrcValue);

        OutputDebugString(args + StrAsterisk + StrAsterisk+ StrAsterisk + StrSpace + 
          StrOpenBracket + destMemValueStr + StrCloseBracket + StrComma + srcValueStr + StrEnter);
    }
    else
    {
        // register
        if(!SetRegValue(descOperand, dSrcValue))
            return false;

        CString srcValueStr;
        srcValueStr.Format(_T("%#x "), dSrcValue);
        OutputDebugString(args + StrAsterisk + StrAsterisk+ StrAsterisk + StrSpace + 
            descOperand + StrComma + srcValueStr + StrEnter);
    }
    return true;
}

bool DisasmExecMgr::DoMOVZX(CString args)
{    
    CString descOperand;
    if(!GetDescOperand(args, descOperand))
        return false;
    CString srcOperand;
    if(!GetSrcOperand(args, srcOperand))
        return false;
    DWORD dSrcValue = GetSrcDWFromStr(srcOperand);
    dSrcValue = GetValueFromAddress(srcOperand, dSrcValue);

    TCHAR srcValueStr[20];
    _ultow_s(dSrcValue, srcValueStr, 20, 16);
    args = StrMov + StrSpace + descOperand + StrComma + srcValueStr;
    Execute(args);
    return true;
}

bool DisasmExecMgr::DoPUSH(CString args)
{
    CString descOperand;
    if(!GetDescOperand(args, descOperand))
        return false;

    // PUSH DWORD PTR [ESP + 8]
    DWORD dESPValue = GetRealValue(StrESP);
    dESPValue -= 4;
    TCHAR destESP[20];
    _ultow_s(dESPValue, destESP, 20, 16);

    args = StrMov + StrSpace + StrDWORDPTR + StrOpenBracket + destESP + StrCloseBracket + 
        StrComma + descOperand; // "DWORD PTR [esp], descOperand" ;
    Execute(args);

    if(!SetRegValue(StrESP,  dESPValue))
        return false;
    return true;
}

bool DisasmExecMgr::DoPOP(CString args)
{
    CString descOperand;
    if(!GetDescOperand(args, descOperand))
        return false;   
    args = StrMov + StrSpace + descOperand + StrComma + 
        StrDWORDPTR + StrOpenBracket + StrESP + StrCloseBracket; // "descOperand, DWORD PTR [esp]" ;
    Execute(args);

    args = StrMov + StrSpace + StrESP + StrComma + StrESP + StrPlus + _T("4"); //"esp, esp+4";
    Execute(args);

    return true;
}

bool DisasmExecMgr::DoSUB(CString args)
{
    CString descOperand;
    if(!GetDescOperand(args, descOperand))
        return false;
    CString srcOperand;
    if(!GetSrcOperand(args, srcOperand))
        return false;

    DWORD dSrcValue = GetSrcDWFromStr(srcOperand);
    dSrcValue = GetValueFromAddress(srcOperand, dSrcValue);
    DWORD dDestValue = GetSrcDWFromStr(descOperand);
    dDestValue = GetValueFromAddress(descOperand, dDestValue);
    dSrcValue = dDestValue - dSrcValue;
    SetResult(dSrcValue);
    SetCF( (dSrcValue>>31) != 0);
    TCHAR srcValueStr[20];
    _ultow_s(dSrcValue, srcValueStr, 20, 16);
    args = StrMov + StrSpace + descOperand + StrComma + srcValueStr;  
    Execute(args);
    return true;
}

bool DisasmExecMgr::DoSBB(CString args)
{
    CString descOperand;
    if(!GetDescOperand(args, descOperand))
        return false;
    CString srcOperand;
    if(!GetSrcOperand(args, srcOperand))
        return false;

    DWORD dSrcValue = GetSrcDWFromStr(srcOperand);
    dSrcValue = GetValueFromAddress(srcOperand, dSrcValue);
    DWORD dDestValue = GetSrcDWFromStr(descOperand);
    dDestValue = GetValueFromAddress(descOperand, dDestValue);
    dSrcValue = dDestValue - (dSrcValue + GetCF());
    SetResult(dSrcValue);
    TCHAR srcValueStr[20];
    _ultow_s(dSrcValue, srcValueStr, 20, 16);
    args = StrMov + StrSpace + descOperand + StrComma + srcValueStr;  
    Execute(args);
    return true;
}

bool DisasmExecMgr::DoADD(CString args)
{
    CString descOperand;
    if(!GetDescOperand(args, descOperand))
        return false;
    CString srcOperand;
    if(!GetSrcOperand(args, srcOperand))
        return false;

    DWORD dSrcValue = GetSrcDWFromStr(srcOperand);
    dSrcValue = GetValueFromAddress(srcOperand, dSrcValue);
    DWORD dDestValue = GetSrcDWFromStr(descOperand);
    dDestValue = GetValueFromAddress(descOperand, dDestValue);
    dSrcValue = dDestValue + dSrcValue;
    SetResult(dSrcValue);
    TCHAR srcValueStr[20];
    _ultow_s(dSrcValue, srcValueStr, 20, 16);
    args = StrMov + StrSpace + descOperand + StrComma + srcValueStr;  
    Execute(args);
    return true;
}

bool DisasmExecMgr::DoXOR(CString args)
{
    CString descOperand;
    if(!GetDescOperand(args, descOperand))
        return false;
    CString srcOperand;
    if(!GetSrcOperand(args, srcOperand))
        return false;

    DWORD dSrcValue = GetSrcDWFromStr(srcOperand);
    dSrcValue = GetValueFromAddress(srcOperand, dSrcValue);
    DWORD dDestValue = GetSrcDWFromStr(descOperand);
    dDestValue = GetValueFromAddress(descOperand, dDestValue);
    dSrcValue = dDestValue ^ dSrcValue;
    TCHAR srcValueStr[20];
    _ultow_s(dSrcValue, srcValueStr, 20, 16);
    args = StrMov + StrSpace + descOperand + StrComma + srcValueStr;  
    Execute(args);
    SetResult(dSrcValue);
    return true;
}

bool DisasmExecMgr::DoAND(CString args)
{
    CString descOperand;
    if(!GetDescOperand(args, descOperand))
        return false;
    CString srcOperand;
    if(!GetSrcOperand(args, srcOperand))
        return false;

    DWORD dSrcValue = GetSrcDWFromStr(srcOperand);
    dSrcValue = GetValueFromAddress(srcOperand, dSrcValue);
    DWORD dDestValue = GetSrcDWFromStr(descOperand);
    dDestValue = GetValueFromAddress(descOperand, dDestValue);
    dSrcValue = dDestValue & dSrcValue;
    TCHAR srcValueStr[20];
    _ultow_s(dSrcValue, srcValueStr, 20, 16);
    args = StrMov + StrSpace + descOperand + StrComma + srcValueStr;  
    Execute(args);

    SetResult(dSrcValue);
    return true;
}

bool DisasmExecMgr::DoLEA(CString args)
{    
    CString descOperand;
    if(!GetDescOperand(args, descOperand))
        return false;
    CString srcOperand;
    if(!GetSrcOperand(args, srcOperand))
        return false;
    DWORD dSrcValue = GetSrcDWFromStr(srcOperand);
    TCHAR srcValueStr[20];
    _ultow_s(dSrcValue, srcValueStr, 20, 16);

    args = StrMov + StrSpace + descOperand + StrComma + srcValueStr;
    Execute(args);
    return true;
}

bool DisasmExecMgr::DoCALL(CString args)
{
    m_iCallLevel++;
    if(m_pInstructionMgr == NULL)
        return false;
    IByteStreamReader* pReader = m_pInstructionMgr->GetByteReader();
    if(pReader == NULL)
        return false; 
    CString descOperand;
    if(!GetDescOperand(args, descOperand))
        return false;
    DWORD curAddr = (DWORD) (pReader->GetCurrentBaseAddr());
    TCHAR srcValueStr[20];
    _ultow_s(curAddr, srcValueStr, 20, 16);
    args = StrPush + StrSpace + srcValueStr;
    Execute(args);

    args = StrJMP + StrSpace + descOperand; //"Jmp dest";
    Execute(args);

    return true;
}

bool DisasmExecMgr::DoJMP(CString args)
{
    if(m_pInstructionMgr == NULL)
        return false;
    IByteStreamReader* pReader = m_pInstructionMgr->GetByteReader();
    if(pReader == NULL)
        return false; 
    CString descOperand;
    if(!GetDescOperand(args, descOperand))
        return false;
    DWORD dDestValue = GetSrcDWFromStr(descOperand);
    dDestValue = GetValueFromAddress(descOperand, dDestValue);
    if(m_execRule != NULL)
        m_execRule->FixCallAddress(dDestValue);
    pReader->SetCurrentBaseAddress((void*)dDestValue);
    //for(int i = 0; i < m_iCallLevel; i++)
    //  OutputDebugString(StrSpace);

    CString debugStr;
    debugStr.Format(_T("%#x "), dDestValue);
    args = _T("IP Changes Here to ") + debugStr + _T("\n");
    OutputDebugString(args);
    return true;
}

bool DisasmExecMgr::DoIMUL(CString args)
{
  CString descOperand;
  if(!GetDescOperand(args, descOperand))
    return false;
  CString srcOperand;
  if(!GetSrcOperand(args, srcOperand))
    return false;
  CString srcOperand1 = srcOperand;
  CString srcOperand2 = _T("1");
  if(FindInstructionDNA(srcOperand, StrComma))
  {
    if(!GetSrcOperand2(srcOperand, srcOperand1, srcOperand2))
      return false;
  }

  DWORD dSrcValue1 = GetSrcDWFromStr(srcOperand1);
  dSrcValue1= GetValueFromAddress(srcOperand, dSrcValue1);
  DWORD dSrcValue2 = GetSrcDWFromStr(srcOperand2);
  dSrcValue2= GetValueFromAddress(srcOperand, dSrcValue2);
  DWORD dDestValue = GetSrcDWFromStr(descOperand);
  dDestValue = GetValueFromAddress(descOperand, dDestValue);

  dSrcValue2 = dSrcValue1 * dSrcValue2;
  SetResult(dSrcValue2);

  TCHAR srcValueStr[20];
  _ultow_s(dSrcValue2, srcValueStr, 20, 16);
  args = StrMov + StrSpace + descOperand + StrComma + srcValueStr;  
  Execute(args);

  return true;
}


bool DisasmExecMgr::DoTEST(CString args)
{
    CString descOperand;
    if(!GetDescOperand(args, descOperand))
        return false;
    CString srcOperand;
    if(!GetSrcOperand(args, srcOperand))
        return false;

    DWORD dSrcValue = GetSrcDWFromStr(srcOperand);
    dSrcValue = GetValueFromAddress(srcOperand, dSrcValue);
    DWORD dDestValue = GetSrcDWFromStr(descOperand);
    dDestValue = GetValueFromAddress(descOperand, dDestValue);
    dSrcValue = dDestValue & dSrcValue;
    SetResult(dSrcValue);
    return true;
}

bool DisasmExecMgr::DoJE(CString args)
{
    if(m_pInstructionMgr == NULL)
        return false;
    IByteStreamReader* pReader = m_pInstructionMgr->GetByteReader();
    if(pReader == NULL)
        return false; 
    CString descOperand;
    if(!GetDescOperand(args, descOperand))
        return false;
    if(GetResult() == 0)
    {
        DWORD dDestValue = GetSrcDWFromStr(descOperand);
        dDestValue = GetValueFromAddress(descOperand, dDestValue);
        pReader->SetCurrentBaseAddress( (void*) dDestValue);
        //for(int i = 0; i < m_iCallLevel; i++)
        //  OutputDebugString(StrSpace);
        CString debugStr;
        debugStr.Format(_T("%#x "), dDestValue);
        args = _T("IP Changes Here to ") + debugStr + _T("\n");
        OutputDebugString(args);
    }
    return true;
}

bool DisasmExecMgr::DoJNE(CString args)
{
    if(m_pInstructionMgr == NULL)
        return false;
    IByteStreamReader* pReader = m_pInstructionMgr->GetByteReader();
    if(pReader == NULL)
        return false; 
    CString descOperand;
    if(!GetDescOperand(args, descOperand))
        return false;
    if(GetResult() != 0)
    {
        DWORD dDestValue = GetSrcDWFromStr(descOperand);
        dDestValue = GetValueFromAddress(descOperand, dDestValue);
        pReader->SetCurrentBaseAddress( (void*) dDestValue);
        //for(int i = 0; i < m_iCallLevel; i++)
        //  OutputDebugString(StrSpace);
        CString debugStr;
        debugStr.Format(_T("%#x "), dDestValue);
        args = _T("IP Changes Here to ") + debugStr + _T("\n");
        OutputDebugString(args);
    }
    return true;
}

bool DisasmExecMgr::DoRET(CString args)
{
  m_iCallLevel--;
  if(m_pInstructionMgr == NULL)
    return false;
  IByteStreamReader* pReader = m_pInstructionMgr->GetByteReader();
  if(pReader == NULL)
    return false; 
  Execute(StrPop + StrSpace + StrEIP); 
  DWORD eipAddr = 0;
  eipAddr = GetRealValue(StrEIP);
  pReader->SetCurrentBaseAddress( (void*) eipAddr);
  CString descOperand;
  if(GetDescOperand(args, descOperand))
  {
    DWORD dDestValue = GetSrcDWFromStr(descOperand);
    dDestValue = GetValueFromAddress(descOperand, dDestValue);
    char Imm32Char[12];
    _itoa_s(dDestValue, Imm32Char, 12, 16);
    CString tempStr(Imm32Char);
    args = StrMov + StrSpace + StrESP + StrComma + StrESP + StrPlus + tempStr;
    Execute(args);
  }      

  return true;
}


bool DisasmExecMgr::DoCMP(CString args)
{
    CString descOperand;
    if(!GetDescOperand(args, descOperand))
        return false;
    CString srcOperand;
    if(!GetSrcOperand(args, srcOperand))
        return false;

    DWORD dSrcValue = GetSrcDWFromStr(srcOperand);
    dSrcValue = GetValueFromAddress(srcOperand, dSrcValue);
    DWORD dDestValue = GetSrcDWFromStr(descOperand);
    dDestValue = GetValueFromAddress(descOperand, dDestValue);
    if(m_execRule != NULL )
    {
        m_execRule->FixAddress(dDestValue);
        m_execRule->FixAddress(dSrcValue);
    }
    dSrcValue = dDestValue - dSrcValue;
    SetResult(dSrcValue);
    return true;
}

bool DisasmExecMgr::DoCMPXCHG(CString args)
{
  CString descOperand;
  if(!GetDescOperand(args, descOperand))
    return false;
  CString srcOperand;
  if(!GetSrcOperand(args, srcOperand))
    return false;

  args = StrCmp + StrSpace + descOperand + StrComma + StrEAX;
  Execute(args);
  if(GetResult() == 0)
  {
    args = StrMov + StrSpace + descOperand + StrComma + srcOperand;
    Execute(args);
  }
  else
  {
    args = StrMov + StrSpace + StrAL + StrComma + srcOperand;
    Execute(args);
  }
  return true;
}
bool DisasmExecMgr::DoJAE(CString args)
{
  if(m_pInstructionMgr == NULL)
    return false;
  IByteStreamReader* pReader = m_pInstructionMgr->GetByteReader();
  if(pReader == NULL)
    return false; 
  CString descOperand;
  if(!GetDescOperand(args, descOperand))
    return false;
  if( (GetResult() >> 31) == 0)
  {
    DWORD dDestValue = GetSrcDWFromStr(descOperand);
    dDestValue = GetValueFromAddress(descOperand, dDestValue);
    pReader->SetCurrentBaseAddress( (void*) dDestValue);
    //for(int i = 0; i < m_iCallLevel; i++)
    //  OutputDebugString(StrSpace);
    CString debugStr;
    debugStr.Format(_T("%#x "), dDestValue);
    args = _T("IP Changes Here to ") + debugStr + _T("\n");
    OutputDebugString(args);
  }
  return true;
}
bool DisasmExecMgr::DoJBE(CString args)
{
    if(m_pInstructionMgr == NULL)
        return false;
    IByteStreamReader* pReader = m_pInstructionMgr->GetByteReader();
    if(pReader == NULL)
        return false; 
    CString descOperand;
    if(!GetDescOperand(args, descOperand))
        return false;
    if( ((GetResult() >> 31) != 0) || (GetResult() == 0) )
    {
        DWORD dDestValue = GetSrcDWFromStr(descOperand);
        dDestValue = GetValueFromAddress(descOperand, dDestValue);
        pReader->SetCurrentBaseAddress( (void*) dDestValue);
        //for(int i = 0; i < m_iCallLevel; i++)
        //  OutputDebugString(StrSpace);
        CString debugStr;
        debugStr.Format(_T("%#x "), dDestValue);
        args = _T("IP Changes Here to ") + debugStr + _T("\n");
        OutputDebugString(args);
    }
    return true;
}

bool DisasmExecMgr::DoJB(CString args)
{
  if(m_pInstructionMgr == NULL)
    return false;
  IByteStreamReader* pReader = m_pInstructionMgr->GetByteReader();
  if(pReader == NULL)
    return false; 
  CString descOperand;
  if(!GetDescOperand(args, descOperand))
    return false;
  if( ((GetResult() >> 31) != 0) && (GetResult() != 0))
  {
    DWORD dDestValue = GetSrcDWFromStr(descOperand);
    dDestValue = GetValueFromAddress(descOperand, dDestValue);
    pReader->SetCurrentBaseAddress( (void*) dDestValue);
    //for(int i = 0; i < m_iCallLevel; i++)
    //  OutputDebugString(StrSpace);
    CString debugStr;
    debugStr.Format(_T("%#x "), dDestValue);
    args = _T("IP Changes Here to ") + debugStr + _T("\n");
    OutputDebugString(args);
  }
  return true;
}


bool DisasmExecMgr::DoJA(CString args)
{
    if(m_pInstructionMgr == NULL)
        return false;
    IByteStreamReader* pReader = m_pInstructionMgr->GetByteReader();
    if(pReader == NULL)
        return false; 
    CString descOperand;
    if(!GetDescOperand(args, descOperand))
        return false;
    if( (GetResult() >> 31) == 0 && (GetResult() != 0) )
    {
        DWORD dDestValue = GetSrcDWFromStr(descOperand);
        dDestValue = GetValueFromAddress(descOperand, dDestValue);
        pReader->SetCurrentBaseAddress( (void*) dDestValue);
        //for(int i = 0; i < m_iCallLevel; i++)
        //  OutputDebugString(StrSpace);
        CString debugStr;
        debugStr.Format(_T("%#x "), dDestValue);
        args = _T("IP Changes Here to ") + debugStr + _T("\n");
        OutputDebugString(args);
    }
    return true;
}

bool DisasmExecMgr::DoOR(CString args)
{
    CString descOperand;
    if(!GetDescOperand(args, descOperand))
        return false;
    CString srcOperand;
    if(!GetSrcOperand(args, srcOperand))
        return false;

    DWORD dSrcValue = GetSrcDWFromStr(srcOperand);
    dSrcValue = GetValueFromAddress(srcOperand, dSrcValue);
    DWORD dDestValue = GetSrcDWFromStr(descOperand);
    dDestValue = GetValueFromAddress(descOperand, dDestValue);
    dSrcValue = dDestValue | dSrcValue;
    TCHAR srcValueStr[20];
    _ultow_s(dSrcValue, srcValueStr, 20, 16);
    args = StrMov + StrSpace + descOperand + StrComma + srcValueStr;  
    Execute(args);
    return true;
}

bool DisasmExecMgr::DoINC(CString args)
{
    CString descOperand;
    if(!GetDescOperand(args, descOperand))
        return false;

    DWORD dSrcValue = 1;
    TCHAR srcValueStr[20];
    _ultow_s(dSrcValue, srcValueStr, 20, 16);
    args = StrAdd + StrSpace + descOperand + StrComma + srcValueStr;  
    Execute(args);
    return true;
}

bool DisasmExecMgr::DoDEC(CString args)
{
  CString descOperand;
  if(!GetDescOperand(args, descOperand))
    return false;

  DWORD dSrcValue = 1;
  TCHAR srcValueStr[20];
  _ultow_s(dSrcValue, srcValueStr, 20, 16);
  args = StrSub + StrSpace + descOperand + StrComma + srcValueStr;  
  Execute(args); 
  return true;
}

bool DisasmExecMgr::DoSTC(CString args)
{
  SetCF(true);
  return true;
}
bool DisasmExecMgr::DoNEG(CString args)
{
    CString descOperand;
    if(!GetDescOperand(args, descOperand))
        return false;
    DWORD dDestValue = GetSrcDWFromStr(descOperand);
    dDestValue = GetValueFromAddress(descOperand, dDestValue);
    dDestValue = 0 - dDestValue;
    TCHAR srcValueStr[20];
    _ultow_s(dDestValue, srcValueStr, 20, 16);
    args = StrMov + StrSpace + descOperand + StrComma + srcValueStr;  
    Execute(args);
    SetResult(dDestValue);
    SetCF(dDestValue != 0);
    return true;
}


bool DisasmExecMgr::DoSAL(CString args)
{
  CString descOperand;
  if(!GetDescOperand(args, descOperand))
    return false;

  int bByte = 4;
  if(FindInstructionDNA(descOperand, StrBYTEPTR))
    bByte = 1;
  else if(FindInstructionDNA(descOperand, StrWORDPTR))
    bByte = 2;
  else if(FindInstructionDNA(descOperand, StrDWORDPTR))
    bByte = 4;

  CString srcOperand;
  if(!GetSrcOperand(args, srcOperand))
    return false;

  DWORD dSrcValue = GetSrcDWFromStr(srcOperand);
  dSrcValue = GetValueFromAddress(srcOperand, dSrcValue);
  DWORD dDestValue = GetSrcDWFromStr(descOperand);
  dDestValue = GetValueFromAddress(descOperand, dDestValue);
  
  for(UINT i = 0; i < dSrcValue; i++)
  {
    // Set C reg value
    switch (bByte)
    {
    case 1:
      {
        SetCF(!!(dDestValue & 0x80));
        break;
      }
    case 2:
      {
        SetCF(!!(dDestValue & 0x8000));
        break;
      }
    case 4:
      {
        SetCF(!!(dDestValue & 0x80000000));
        break;
      }
    }
    dDestValue = dDestValue << 1;
  }

  TCHAR dDestValueStr[20];
  _ultow_s(dDestValue, dDestValueStr, 20, 16);
  
  args = StrMov + StrSpace + descOperand + StrComma + dDestValueStr;  
  Execute(args);
  return true;
}

bool DisasmExecMgr::DoSHR(CString args)
{
  CString descOperand;
  if(!GetDescOperand(args, descOperand))
    return false;

  CString srcOperand;
  if(!GetSrcOperand(args, srcOperand))
    return false;

  DWORD dSrcValue = GetSrcDWFromStr(srcOperand);
  dSrcValue = GetValueFromAddress(srcOperand, dSrcValue);
  DWORD dDestValue = GetSrcDWFromStr(descOperand);
  dDestValue = GetValueFromAddress(descOperand, dDestValue);

  for(UINT i = 0; i < dSrcValue; i++)
  {
    // Set C reg value
    SetCF(dDestValue & 0x01);
    dDestValue = dDestValue >> 1;
  }

  TCHAR dDestValueStr[20];
  _ultow_s(dDestValue, dDestValueStr, 20, 16);

  args = StrMov + StrSpace + descOperand + StrComma + dDestValueStr;  
  Execute(args);
  return true;
}

bool DisasmExecMgr::DoREP(CString args)
{
  if(!FindInstructionDNA(args, StrREP + StrSpace))
    return false;
  args.Replace(StrREP + StrSpace, StrEmpty);
  DWORD count = GetRealValue(StrECX);
  CString descOperand;
  if(!GetDescOperand(args, descOperand))
    return false;

  int bByte = 4;
  if(FindInstructionDNA(descOperand, StrBYTEPTR))
  {
    bByte = 1;
    descOperand.Replace(StrBYTEPTR, StrEmpty);
  }
  else if(FindInstructionDNA(descOperand, StrDWORDPTR))
  {
    bByte = 4;
    descOperand.Replace(StrDWORDPTR, StrEmpty);
  }  
  else if(FindInstructionDNA(descOperand, StrWORDPTR))
  {
    bByte = 2;
    descOperand.Replace(StrWORDPTR, StrEmpty);
  }
  descOperand.Replace(StrOpenBracket, StrEmpty);
  descOperand.Replace(StrCloseBracket, StrEmpty);

  TCHAR dDestValueStr[20];
  _ultow_s(bByte, dDestValueStr, 20, 16);

  for (UINT i = 0; i < count; i++)
  {
    Execute(args);
    // update args edi
    CString StrUpdate;
    if(GetDF())
    {
      StrUpdate = StrMov + StrSpace + descOperand + StrComma + descOperand +
        StrNegetive + dDestValueStr;
    }
    else
    {
      StrUpdate = StrMov + StrSpace + descOperand + StrComma + descOperand +
        StrPlus + dDestValueStr;
    }
    Execute(StrUpdate);
    m_ct.Ecx--;
  }
  return true;
}

bool DisasmExecMgr::DoSTOS(CString args)
{
  args.Replace(StrSTOS , StrMov);
  Execute(args);
  return true;
}

bool DisasmExecMgr::DoSETNE(CString args)
{
    CString descOperand;
    if(!GetDescOperand(args, descOperand))
        return false;

    if( GetResult() != 0) 
    {
        DWORD dSrcValue = 1;
        TCHAR srcValueStr[20];
        _ultow_s(dSrcValue, srcValueStr, 20, 16);
        args = StrMov + StrSpace + descOperand + StrComma + srcValueStr;  
        Execute(args);
    }
    return true;
}

bool DisasmExecMgr::DoSETE(CString args)
{
    CString descOperand;
    if(!GetDescOperand(args, descOperand))
        return false;

    if( GetResult() == 0) 
    {
        DWORD dSrcValue = 1;
        TCHAR srcValueStr[20];
        _ultow_s(dSrcValue, srcValueStr, 20, 16);
        args = StrMov + StrSpace + descOperand + StrComma + srcValueStr;  
        Execute(args);
    }
    return true;
}

bool DisasmExecMgr::DoInterrupt(CString args)
{  
  CString descOperand;
  if(!GetDescOperand(args, descOperand))
    return false;
  DWORD dInterrupt_num = GetSrcDWFromStr(descOperand);
  if(dInterrupt_num == 3)
  {
    // break point 
    // trace info here
    return false;
  }
  return false;
}
DWORD DisasmExecMgr::GetSrcDWFromStr(CString opCodeStr)
{
    DWORD dwValue = 0;
    bool bIsSrcMemFormat = IsMemAddrFormat(opCodeStr);
    // byte operator
    bool bByteOp = false;
    if(FindInstructionDNA(opCodeStr, StrBYTEPTR) )
    {
        opCodeStr.Replace(StrBYTEPTR, StrEmpty);
        bByteOp = true;
    }
    opCodeStr.Replace(StrDWORDPTR, StrEmpty);
    // Get Segment override
    CString segOverrideStr;
    if(FindInstructionDNA(opCodeStr, StrFS))
    {
        segOverrideStr = StrFS;
        opCodeStr.Replace(segOverrideStr, StrEmpty);
    }
    if(bIsSrcMemFormat)
    {
        opCodeStr.Replace(StrOpenBracket, StrEmpty);
        opCodeStr.Replace(StrCloseBracket, StrEmpty);
    }
    dwValue = PraseStr(opCodeStr);
    if(!segOverrideStr.IsEmpty())
    {
        if(FindInstructionDNA(segOverrideStr, StrFS))
        {
            dwValue = GetFS() + dwValue;
        }
    }
    return dwValue;
}

DWORD DisasmExecMgr::PraseStr(CString opCodeStr)
{
    DWORD dwValue = 0;
    if(FindInstructionDNA(opCodeStr, StrPlus))
    {
        int iPlusPos = opCodeStr.Find(StrPlus);
        CString strLeftOp = opCodeStr.Left(iPlusPos);
        CString strRightOp = opCodeStr.Right(opCodeStr.GetLength() - iPlusPos - 1);
        dwValue = PraseStr(strLeftOp) + PraseStr(strRightOp);
    }
    else if(FindInstructionDNA(opCodeStr, StrNegetive))
    {
        int iNegPos = opCodeStr.Find(StrNegetive);
        CString strLeftOp = opCodeStr.Left(iNegPos);
        CString strRightOp = opCodeStr.Right(opCodeStr.GetLength() - iNegPos - 1);
        dwValue = PraseStr(strLeftOp) - PraseStr(strRightOp);
    }
    else if(FindInstructionDNA(opCodeStr, StrAsterisk))
    {
        int iStarPos = opCodeStr.Find(StrAsterisk);
        CString strLeftOp = opCodeStr.Left(iStarPos);
        CString strRightOp = opCodeStr.Right(opCodeStr.GetLength() - iStarPos - 1);
        dwValue = PraseStr(strLeftOp) * PraseStr(strRightOp);
    }
    else
    {
        dwValue = GetRealValue(opCodeStr);
    }
    return dwValue;
}

DWORD DisasmExecMgr::GetRealValue(CString opCodeStr)
{
    DWORD dwValue = 0;
    if(FindInstructionDNA(opCodeStr, StrEAX))
        return m_ct.Eax;
    if(FindInstructionDNA(opCodeStr, StrECX))
        return m_ct.Ecx;
    if(FindInstructionDNA(opCodeStr, StrEDX))
        return m_ct.Edx;
    if(FindInstructionDNA(opCodeStr, StrEBX))
        return m_ct.Ebx;
    if(FindInstructionDNA(opCodeStr, StrESP))
        return m_ct.Esp;
    if(FindInstructionDNA(opCodeStr, StrEBP))
        return m_ct.Ebp;
    if(FindInstructionDNA(opCodeStr, StrESI))
        return m_ct.Esi;
    if(FindInstructionDNA(opCodeStr, StrEDI))
        return m_ct.Edi;
    if(FindInstructionDNA(opCodeStr, StrAL))
        return m_ct.Eax & 0xff;
    if(FindInstructionDNA(opCodeStr, StrCL))
        return m_ct.Ecx & 0xff;;
    if(FindInstructionDNA(opCodeStr, StrDL))
        return m_ct.Edx & 0xff;;
    if(FindInstructionDNA(opCodeStr, StrBL))
        return m_ct.Ebx & 0xff;;
    if(FindInstructionDNA(opCodeStr, StrEIP))
        return m_ct.Eip;
    dwValue = wcstoul(opCodeStr, 0, 16);
    return dwValue;
}

bool DisasmExecMgr::SetRegValue(CString opCodeStr, DWORD dSrcValue)
{
    if(FindInstructionDNA(opCodeStr, StrEAX))
        m_ct.Eax = dSrcValue;
    else if(FindInstructionDNA(opCodeStr, StrECX))
        m_ct.Ecx = dSrcValue;
    else if(FindInstructionDNA(opCodeStr, StrEDX))
        m_ct.Edx = dSrcValue;
    else if(FindInstructionDNA(opCodeStr, StrEBX))
        m_ct.Ebx = dSrcValue;
    else if(FindInstructionDNA(opCodeStr, StrESP))
        m_ct.Esp = dSrcValue;
    else if(FindInstructionDNA(opCodeStr, StrEBP))
        m_ct.Ebp = dSrcValue;
    else if(FindInstructionDNA(opCodeStr, StrESI))
        m_ct.Esi = dSrcValue;
    else if(FindInstructionDNA(opCodeStr, StrEDI))
        m_ct.Edi = dSrcValue;
    else if(FindInstructionDNA(opCodeStr, StrAL))
        m_ct.Eax = (m_ct.Eax & 0xffffff00) + (dSrcValue & 0xff);
    else if(FindInstructionDNA(opCodeStr, StrCL))
        m_ct.Ecx = (m_ct.Ecx & 0xffffff00) + (dSrcValue & 0xff);
    else if(FindInstructionDNA(opCodeStr, StrDL))
        m_ct.Edx = (m_ct.Edx & 0xffffff00) + (dSrcValue & 0xff);
    else if(FindInstructionDNA(opCodeStr, StrBL))
        m_ct.Ebx = (m_ct.Ebx & 0xffffff00) + (dSrcValue & 0xff);
    else if(FindInstructionDNA(opCodeStr, StrEIP))
        m_ct.Eip = dSrcValue;
    else
        return false;
    return true;
}

DWORD DisasmExecMgr::GetValueFromAddress(CString opCodeStr, DWORD effectAddr)
{
    if(m_pInstructionMgr == NULL)
        return false;
    IByteStreamReader* pReader = m_pInstructionMgr->GetByteReader();
    if(pReader == NULL)
        return false; 
    // 09/1/5 Memory Align
    DWORD dOffset = 0;
    DWORD dActualAddress = effectAddr;
    if( (effectAddr % 4 ) != 0)
    {
        dOffset = (effectAddr % 4 );
        dActualAddress = effectAddr - dOffset;
    }
    // Find in owner Mem Map First
    // not found read from process Mem and add into Mem Map
    DWORD hValue = 0;
    DWORD lValue = 0;
    if(IsMemAddrFormat(opCodeStr))
    {
        if(m_memMap.find(dActualAddress) == m_memMap.end())
        {
             DWORD address = dActualAddress;
             m_debugProcessReader->SetCurrentBaseAddress((void*)address);
             m_debugProcessReader->ReadBytesFromMemAddr(&lValue, sizeof(DWORD)); 
             m_memMap[address] = lValue;
             if(m_memMap.find(dActualAddress + 4) == m_memMap.end())
             {
                 address = dActualAddress + 4;
                 m_debugProcessReader->SetCurrentBaseAddress((void*)address);
                 m_debugProcessReader->ReadBytesFromMemAddr(&hValue, sizeof(DWORD)); 
                 m_memMap[address] = hValue;
             }
             else
             {
                 hValue = m_memMap[address];
             }
        }
        else
        {
            lValue = m_memMap[dActualAddress];
            DWORD address = dActualAddress + 4;
            if(m_memMap.find(dActualAddress + 4) == m_memMap.end())
            {
                m_debugProcessReader->SetCurrentBaseAddress((void*)address);
                m_debugProcessReader->ReadBytesFromMemAddr(&hValue, sizeof(DWORD)); 
                m_memMap[address] = hValue;
            }
            else
            {
                hValue = m_memMap[address];
            }
        }
        // Need check Ptr type.
        DWORD value[2] = {lValue, hValue};
        int iBytetype = 4;
        if(FindInstructionDNA(opCodeStr, StrBYTEPTR))
        {
            iBytetype = 1;
        }
        else if(FindInstructionDNA(opCodeStr, StrDWORDPTR))
        {
            iBytetype = 4;
        }  
        else if(FindInstructionDNA(opCodeStr, StrWORDPTR))
        {
            iBytetype = 2;
        }
        effectAddr = 0;
        memcpy(&effectAddr, (BYTE*)value + dOffset, iBytetype);
    }
    return effectAddr;
}

void DisasmExecMgr::SetResult(DWORD result)
{
    m_result = result;
}
DWORD DisasmExecMgr::GetResult()
{
   return m_result;
}
bool DisasmExecMgr::GetDF()
{
  return (m_ct.EFlags & 0x400) != 0;
}
bool DisasmExecMgr::GetCF()
{
    return (m_ct.EFlags & 0x01);
}
void DisasmExecMgr::SetCF(bool bCF)
{
    m_ct.EFlags = (m_ct.EFlags & 0xfffffffe) + (DWORD)bCF;
}

bool DisasmExecMgr::SetValueToAddress(DWORD address, DWORD dSrcValue, int iByteType)
{
    char AddressChar[12];
    _itoa_s(address, AddressChar, 12, 16);
    CString tempStr(AddressChar);
    DWORD tempValue = GetValueFromAddress(StrOpenBracket + tempStr + StrCloseBracket, address);
    if(tempValue == dSrcValue)
        return true;
    DWORD hValue = 0;
    DWORD lValue = 0;    
    DWORD dOffset = (address % 4);
    lValue = m_memMap[address - dOffset];
    hValue = m_memMap[address - dOffset + 4];
    DWORD value[2] = {lValue, hValue};
    memcpy( (BYTE*)value + dOffset, &dSrcValue, iByteType);
    m_memMap[address - dOffset] = value[0];
    m_memMap[address - dOffset + 4] = value[1];
    return true;
}
